package cn.dengta.webapp.user.service;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import cn.dengta.common.context.Env;
import cn.dengta.common.model.Messager;
import cn.dengta.context.web.ImageConverter;
import cn.dengta.webapp.user.module.file.*;
import cn.dengta.webapp.user.vo.SecurityTokenVO;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import me.codeplayer.util.X;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService
public class OSSFileServiceImpl extends AbstractFileServiceImpl {

	protected OSSClient client;

	protected void initClient(RemoteConfig config) {
		client = new OSSClient(config.getEndPoint(), (new DefaultCredentialProvider(config.getAccessKeyId(), config.getAccessKeySecret())), null);
	}

	public OSSClient getClient() {
		initClient(remoteConfig);
		return client;
	}

	public void bucketAcl(boolean yesOrNo) {
		getClient().setBucketAcl(remoteConfig.getBucketName(), yesOrNo ? CannedAccessControlList.Private : CannedAccessControlList.PublicRead);
	}

	/**
	 * OSS准备远程文件上传参数
	 * https://help.aliyun.com/document_detail/100624.html
	 * <p>
	 * 配置如下：
	 * file.accessKeyId=xxxxxx
	 * file.accessKeySecret=xxxxxx
	 * file.bucketName=xxxxxx
	 * file.region=oss-cn-shenzhen
	 * file.endPoint=https://<region>.aliyuncs.com
	 * file.accessPoint=
	 * file.namePattern=<dirPrefix>yyyy-MM/dd-HHmmssSSS-rand\:3
	 * # 前台OSS子授权配置
	 * file.subAccessKeyId=xxxxxx
	 * file.subAccessKeySecret=xxxxxx
	 * file.regionId=cn-shenzhen
	 * file.product=Sts
	 * file.endpoint=sts.cn-shenzhen.aliyuncs.com
	 * file.roleArn=xxxxxx
	 * file.roleSessionName=xxxxxx
	 *
	 * @param dirPrefix 路径前缀
	 * @param expireTime 过期时间
	 */
	public SecurityTokenVO getSecurityToken(String dirPrefix, long expireTime, Boolean isPublic) {
		AliyunOSSConfig config = (AliyunOSSConfig) remoteConfig;
		final String[] dirArr = setFileDir(dirPrefix, config.getNamePattern(), isPublic);
		try {
			// 添加 endpoint（直接使用STS endpoint）
			DefaultProfile.addEndpoint(config.getRegionId(), config.getProduct(), config.getSubEndpoint());
			// 构造default profile（参数留空，无需添加region ID）
			IClientProfile profile = DefaultProfile.getProfile(config.getRegionId(), config.getSubAccessKeyId(), config.getSubAccessKeySecret());
			// 用profile构造client
			DefaultAcsClient client = new DefaultAcsClient(profile);
			final AssumeRoleRequest request = new AssumeRoleRequest();
			request.setSysMethod(MethodType.POST);
			request.setRoleArn(config.getRoleArn());
			request.setRoleSessionName(config.getRoleSessionName());
			request.setDurationSeconds(expireTime); // 设置凭证有效时间
			final AssumeRoleResponse response = client.getAcsResponse(request);
			return new SecurityTokenVO(response.getCredentials().getAccessKeyId(),
					response.getCredentials().getAccessKeySecret(),
					response.getCredentials().getSecurityToken(),
					config.getBucketName(),
					config.getRegion(),
					dirArr[0],
					dirArr[1],
					String.valueOf((System.currentTimeMillis() + expireTime * 1000) / 1000));
		} catch (Exception e) {
			throw new IllegalArgumentException(e);
		}
	}

	public String[] setFileDir(String dirPrefix, String namePattern, Boolean isPublic) {
		String endpoint = remoteConfig.getEndPoint();
		final Map<String, String> fileNameContext = FileManagerUtil.buildContext(null, null, isPublic);
		final String dir = dirPrefix + FileManagerUtil.buildNewFileName(X.expectNotEmpty(namePattern, "<dirPrefix>yyyy-MM/dd-HHmmssSSS-rand\\:3"), "", fileNameContext); // 用户上传文件时指定的前缀。
		return new String[] { endpoint, dir };
	}

	public Messager<String> save(InputStream inputStream, String dirPrefix, String dirSuffix, Boolean isPublic) {
		final String[] dirArr = setFileDir(dirPrefix, ((AliyunOSSConfig) remoteConfig).getNamePattern(), isPublic);
		try (InputStream is = inputStream) {
			// 上传Object  https://flala-test.oss-cn-shenzhen.aliyuncs.com/d982/avatar/2022-10/4588ca44bac37abad02f0b05277b606e.png
			getClient().putObject(remoteConfig.getBucketName(), dirArr[1] + dirSuffix, is);
			String url = "https://" + remoteConfig.getBucketName() + '.' + remoteConfig.getEndPoint() + "/" + dirArr[1] + dirSuffix;
			if (!Env.inner()) {
				url = url.replace(ImageConverter.COVER_DOMAIN, ImageConverter.CDN);
			}
			return Messager.hideData(url);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
	}

}
